<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta
        name="viewport"
        content="width=device-width, initial-scale=1.0"
    >
    <title>Three.js GLTF Loader</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .label-wrapper {
            color: #ffffff;
            font-family: Arial, sans-serif;
            font-size: 12px;
            padding: 2px;
            background: rgba(0, 0, 0, 0.6);
            border-radius: 4px;
        }

        .label-content {
            width: 120px;
            text-align: center;
        }

        .label h3 {
            margin: 0;
            font-size: 14px;
            font-weight: bold;
        }

        .label p {
            margin: 2px 0;
        }
    </style>
</head>

<body>
    <!-- 
测试下136版本
127版本
-->
    <div id="scene-container"></div>
    <script type="importmap">
    {
      "imports": {
        "three": "../three/v170/three.module.min.js",
        "GLTFLoader":"../three/v170/GLTFLoader.js",
        "DragControls":"../three/v170/DragControls.js",
        "CSS2DRenderer":"../three/v170/CSS2DRenderer.js",
        "OrbitControls":"../three/v170/OrbitControls.js"
      }
    }
  </script>
    <!-- <script type="importmap">
    {
      "imports": {
        "three": "../three/v136/three.module.js",
        "GLTFLoader":"../three/v136/GLTFLoader.js",
        "DragControls":"../three/v136/DragControls.js",
        "CSS2DRenderer":"../three/v136/CSS2DRenderer.js",
        "OrbitControls":"../three/v136/OrbitControls.js"
      }
    }
  </script> -->

    <script type="module">
        import * as THREE from 'three';
        import { OrbitControls } from "OrbitControls";
        import { GLTFLoader } from "GLTFLoader";
        import { DragControls } from "DragControls";
        import { CSS2DRenderer, CSS2DObject } from "CSS2DRenderer";
        console.log(`gltf1.html 76 [THREE版本]`, THREE.REVISION);

        let scene, camera, renderer, controls, isPaused;
        let labelRenderer = null;
        let RotateCube_01 = null;// 旋转立方体

        function createLabel(object, data) {
            const labelDiv = document.createElement('div');
            labelDiv.className = 'label-wrapper';
            labelDiv.innerHTML = `
                <div class="label-content">
                    <h3>${data.name}</h3>
                    <p>Quantity: ${data.quantity}</p>
                    <p>Stock: ${data.stock}</p>
                </div>
            `;
            const label = new CSS2DObject(labelDiv);
            label.position.set(0, object.geometry.boundingBox.max.y + 0.5, 0);
            object.add(label);

            // 指引线
            const lineGeometry = new THREE.BufferGeometry().setFromPoints([
                new THREE.Vector3(0, 0, 0),
                new THREE.Vector3(0, object.geometry.boundingBox.max.y + 0.5, 0)
            ]);
            const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff });
            const guideLine = new THREE.Line(lineGeometry, lineMaterial);
            object.add(guideLine);
        }
        function addTriangle() {
            const triangleGeometry = new THREE.CircleGeometry(1, 3);
            triangleGeometry.computeBoundingBox();
            const triangleMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
            const triangle = new THREE.Mesh(triangleGeometry, triangleMaterial);
            triangle.position.set(7, -3, -2);
            triangle.userData = { name: 'Yellow Triangle', type: 'CircleGeometry' };
            scene.add(triangle);
            createLabel(triangle, { name: 'Yellow Triangle', quantity: 1, stock: 10 });
        }

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.rotation.set(0, 0, 0);

            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setClearColor(0x5d544a);// 设置画布的颜色
            document.body.appendChild(renderer.domElement);

            labelRenderer = new CSS2DRenderer();
            labelRenderer.setSize(window.innerWidth, window.innerHeight);
            labelRenderer.domElement.style.position = 'absolute';
            labelRenderer.domElement.style.top = '0';
            labelRenderer.domElement.style.pointerEvents = 'none';
            document.getElementById('scene-container').appendChild(labelRenderer.domElement);

            // 创建坐标轴辅助对象
            var axesHelper = new THREE.AxesHelper(20); // 参数5表示轴的长度
            scene.add(axesHelper);

            // 添加控制器
            controls = new OrbitControls(camera, renderer.domElement);

            // 添加光源
            const ambientLight = new THREE.AmbientLight(0xffffff, 1);
            scene.add(ambientLight);

            // 绘制一个三角形
            var geometry_02 = new THREE.CircleGeometry(1, 3); //5 32
            geometry_02.computeBoundingBox();
            var material_02 = new THREE.MeshBasicMaterial({ color: 0xffff00 });
            var cube_02 = new THREE.Mesh(geometry_02, material_02);
            cube_02.position.set(7, 3, -2); // 设置初始位置
            cube_02.userData.name = 'cube_02';
            scene.add(cube_02);

            // 加载纹理
            const textureLoader = new THREE.TextureLoader();
            // const texture = textureLoader.load(a001);// 可以直接设置图片
            const texture = textureLoader.load(
                './images/a_001.png',
                function (texture) {
                    console.log('texture:', texture);
                    // material.map = texture; // 在材质中设置贴图属性
                    // material.needsUpdate = true; // 通知渲染器需要更新材质
                },
                function (xhr) {
                    console.log((xhr.loaded / xhr.total) * 100 + '% loaded'); // 贴图加载进度
                },
                function (err) {
                    console.log('An error happened'); // 贴图加载错误处理
                }
            );
            const geometry_1 = new THREE.BoxGeometry(3, 3, 3);
            geometry_1.computeBoundingBox();
            const material_1 = new THREE.MeshBasicMaterial({
                // color: 0x00ff00,// 会变成绿色
                map: texture,
            });
            const cube_png_1 = new THREE.Mesh(geometry_1, material_1);
            cube_png_1.position.set(-3, 0, 0); // 设置位置
            cube_png_1.userData.name = 'boxue_png_1';
            scene.add(cube_png_1);
            createLabel(cube_png_1, { name: 'cube_png_1', quantity: 5, stock: 20 });


            const geometry_2 = new THREE.BoxGeometry(3, 3, 3);
            geometry_2.computeBoundingBox();
            const material_2 = new THREE.MeshBasicMaterial({
                color: 0x00ff00,// 会变成绿色
                map: texture,
            });
            const cube_png_2 = new THREE.Mesh(geometry_2, material_2);
            cube_png_2.position.set(-7, 0, 0); // 设置位置
            cube_png_2.userData.name = 'boxue_png_2';
            scene.add(cube_png_2);
            createLabel(cube_png_2, { name: 'cube_png_2', quantity: 5, stock: 20 });

            // 添加旋转立方体
            const geometry = new THREE.BoxGeometry(2, 2, 2);
            const material = new THREE.MeshNormalMaterial({
                color: 0x00ff00,// 会变成绿色
            });
            RotateCube_01 = new THREE.Mesh(geometry, material);
            RotateCube_01.position.set(-10, 1, 4);
            RotateCube_01.userData = {
                name: '旋转的立方体',
                age: 20
            };
            scene.add(RotateCube_01);

            // 加载png
            function createWindow(width, height, depth, angle, x, y, z, name) {
                var loader = new THREE.TextureLoader();
                loader.load("images/roll.png", function (texture) {
                    var windowgeometry = new THREE.BoxGeometry(width, height, depth);
                    var windowmaterial = new THREE.MeshBasicMaterial({
                        map: texture,
                        color: 0xffffff,
                    });
                    windowmaterial.opacity = 1.0;
                    windowmaterial.transparent = true;
                    var png_01 = new THREE.Mesh(windowgeometry, windowmaterial);
                    png_01.position.set(x, y, z);
                    png_01.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
                    png_01.name = name;
                    png_01.scale.set(0.2, 0.2, 0.2);
                    png_01.userData = {
                        name: '静态的png图片',
                        age: 20
                    };
                    scene.add(png_01);
                });
            }
            createWindow(40, 40, 2, 0, -9, 0, -8, "路");


            // 加载GLB模型
            const loader = new GLTFLoader();
            var url = 'car.glb';
            var url = '婴儿1.glb';
            var url = 'yang_tuo.glb';
            // var url = 'duck.glb';

            if (['car.glb'].includes(url)) {
                camera.position.set(400, 400, 400);
            } else if (['婴儿1.glb'].includes(url)) {
                camera.position.set(0.5, 0.5, 0.5);
            } else if (['yang_tuo.glb'].includes(url)) {
                camera.position.set(5, 6, 5);
            }

            loader.load('model/' + url, (gltf) => {
                gltf.scene.position.set(4, 0, 0);
                // gltf.scene.scale.set(0.5, 0.5, 0.5)
                gltf.scene.traverse((child) => {
                    if (child.isMesh) {
                        child.geometry.computeBoundingBox();
                        child.userData.name = 'Duck GLB Model'
                        child.userData.type = 'GLBModel'
                    }
                })

                scene.add(gltf.scene);
                const mixer = new THREE.AnimationMixer(gltf.scene);
                gltf.animations.forEach((clip) => {
                    mixer.clipAction(clip).play();
                });
                animate(mixer); // 开始动画循环
            }, undefined, (error) => {
                console.error(error);
            });

            //添加拖动效果
            var objects = [];
            for (var i = 0; i < scene.children.length; i++) {
                var Msg = scene.children[i].name.split("$");
                if (scene.children[i].isMesh) {
                    objects.push(scene.children[i]);// 过滤不是 Mesh 的物体,例如辅助网格
                }
            }
            var dragControls = new DragControls(
                objects,
                camera,
                renderer.domElement
            );
            dragControls.addEventListener("dragstart", function (event) {
                controls.enabled = false;
                isPaused = true;
            });
            dragControls.addEventListener("dragend", function (event) {
                controls.enabled = true;
                isPaused = false;
            });

            // 创建一个Raycaster对象
            var raycaster = new THREE.Raycaster();
            var mouse = new THREE.Vector2();
            // 监听鼠标点击事件
            window.addEventListener('click', onMouseClick, false);
            function onMouseClick(event) {
                // 计算鼠标点击位置在Three.js坐标系中的位置
                mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
                // 更新射线
                raycaster.setFromCamera(mouse, camera);
                // 检测射线与场景中的对象相交
                var intersects = raycaster.intersectObjects(scene.children, true);
                // 如果有相交的对象
                if (intersects.length > 0) {
                    var intersectedObject = intersects[0].object;// 获取第一个相交的对象
                    if (!!intersectedObject.isMesh) {
                        console.log(160, intersectedObject)
                        console.log(`gltf1.html 175 [intersectedObject.userData]`, intersectedObject.userData);

                        if (intersectedObject.geometry) {
                            console.log('几何体类型:', intersectedObject.geometry.type);
                        }

                        if (intersectedObject.material) {
                            console.log('材质类型:', intersectedObject.material.type);
                        }

                        if (intersectedObject.material.map) {
                            console.log('纹理类型:', intersectedObject.material.map.type);
                        }

                        // 如果是GLTF模型对象
                        if (intersectedObject.parent.type === 'GLB') {
                            console.log('点击了GLTF模型对象');
                        }
                    }

                }
            }

            addTriangle();

            // 窗口调整
            window.addEventListener('resize', () => {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            });
        }

        function animate(mixer) {
            requestAnimationFrame(() => animate(mixer));
            RotateCube_01.rotation.x = RotateCube_01.rotation.x + 0.01;// 让立方体旋转
            RotateCube_01.rotation.y = RotateCube_01.rotation.x + 0.01;
            if (mixer) mixer.update(0.01); // 更新动画
            controls.update(); // 更新控制器
            renderer.render(scene, camera); // 渲染场景
            labelRenderer.render(scene, camera); // 渲染标签
        }

        init();
    </script>

</body>

</htm